using QuickFiniteStateMachine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.InputSystem;

enum BaseStateEnum
{
    Idle,
    Fall,
    Move,
    //NearEdge,
    //NearWall,
    Interact
}

public class BaseState : SingletonMonoBehaviour<BaseState>
{
    public float _speed;
    public float _jumpForce;
    public LayerMask _groundLayer;

    private Rigidbody2D _RB;
    private QuickFSM<BaseStateEnum> _FSM;
    private Vector2 _direction;
    private bool _isJumpable;

    private void Awake() { INI_Singleton(); }

    private void Start()
    {
        _RB = GetComponent<Rigidbody2D>();
        InputManager.Instance.UpdateInputEvent(delegate (Vector2 vector2) { _direction = vector2; }, true);
        InputManager.Instance.UpdateInputEvent(GameplayKeyCode.UpArrow, InputActionPhase.Started, delegate
        {
            if (_isJumpable) _RB.AddForce(transform.up * _jumpForce, ForceMode2D.Impulse);
        }, true);
        INI_FSM();
    }

    private void Update() { _FSM.Update(); }

    private void INI_FSM()
    {
        _FSM = new QuickFSM<BaseStateEnum>();
        Action[] events;
        Func<bool>[] conditions;
        BaseStateEnum[] results;
        #region State Idle
        events = new Action[3];
        events[0] = delegate { _isJumpable = true; _RB.velocity = Vector3.zero; };
        conditions = new Func<bool>[] {
            delegate { return _direction.x != 0; },
            delegate { return !IsOnGround(); }
        };
        results = new BaseStateEnum[] { BaseStateEnum.Move, BaseStateEnum.Fall };
        new QuickState<BaseStateEnum>(BaseStateEnum.Idle, _FSM, events, conditions, results);
        #endregion
        #region State Move
        events = new Action[3];
        events[1] = XAxisMove;
        conditions = new Func<bool>[] {
            delegate { return _direction.magnitude == 0; },
            delegate { return !IsOnGround(); }
        };
        results = new BaseStateEnum[] { BaseStateEnum.Idle, BaseStateEnum.Fall };
        new QuickState<BaseStateEnum>(BaseStateEnum.Move, _FSM, events, conditions, results);
        #endregion
        #region Fall
        events = new Action[3];
        events[0] = delegate { _isJumpable = false; };
        //events[1] = Move;
        conditions = new Func<bool>[] { IsOnGround };
        results = new BaseStateEnum[] { BaseStateEnum.Idle };
        new QuickState<BaseStateEnum>(BaseStateEnum.Fall, _FSM, events, conditions, results);
        #endregion
        _FSM.FSMStart(BaseStateEnum.Idle);
    }

    private void XAxisMove()
    {
        _RB.velocity = new Vector3(_direction.x * _speed, _RB.velocity.y, 0);
        if (_direction.x < 0)//flip
        {
            gameObject.transform.localScale = new Vector3(-1, 1, 1);
        }
        else if (_direction.x > 0)
        {
            gameObject.transform.localScale = new Vector3(1, 1, 1);
        }
    }

    private bool IsOnGround()
    {
        return Physics2D.OverlapArea((Vector2)transform.position + new Vector2(-0.4f, -0.6f), (Vector2)transform.position + new Vector2(0.4f, -0.7f), _groundLayer);
    }
}
